home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
lang
/
fpcsrc.lha
/
fpc
/
compiler
/
pstatmnt.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-09-24
|
41KB
|
1,183 lines
{
$Id: pstatmnt.pas,v 1.3.2.1 1998/08/05 14:07:34 pierre Exp $
Copyright (c) 1998 by Florian Klaempfl
Does the parsing of the statements
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit pstatmnt;
interface
uses tree;
var
{ true, if we are in a except block }
in_except_block : boolean;
{ reads a block }
function block(islibrary : boolean) : ptree;
{ reads an assembler block }
function assembler_block : ptree;
implementation
uses
cobjects,scanner,globals,symtable,aasm,pass_1,
types,hcodegen,files,verbose
{ processor specific stuff }
{$ifdef i386}
,i386
,rai386
,ratti386
,radi386
,tgeni386
{$endif}
{$ifdef m68k}
,m68k
,tgen68k
,ag68kmit
,ra68k
,ag68kgas
,ag68kmot
{$endif}
{ parser specific stuff, be careful consume is also defined to }
{ read assembler tokens }
,pbase,pexpr,pdecl;
function statement : ptree;forward;
function if_statement : ptree;
var
ex,if_a,else_a : ptree;
begin
consume(_IF);
ex:=expr;
consume(_THEN);
if token<>_ELSE then
if_a:=statement
else
if_a:=nil;
if token=_ELSE then
begin
consume(_ELSE);
else_a:=statement;
end
else
else_a:=nil;
if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
end;
{ creates a block (list) of statements, til the next END token }
function statements_til_end : ptree;
var
first,last : ptree;
begin
first:=nil;
while token<>_END do
begin
if first=nil then
begin
last:=gennode(anwein,nil,statement);
first:=last;
end
else
begin
last^.left:=gennode(anwein,nil,statement);
last:=last^.left;
end;
if token<>SEMICOLON then
break
else
consume(SEMICOLON);
while token=SEMICOLON do
consume(SEMICOLON);
end;
consume(_END);
statements_til_end:=gensinglenode(blockn,first);
end;
function case_statement : ptree;
var
{ contains the label number of currently parsed case block }
aktcaselabel : plabel;
wurzel : pcaserecord;
{ the typ of the case expression }
casedef : pdef;
procedure newcaselabel(l,h : longint);
var
hcaselabel : pcaserecord;
procedure insertlabel(var p : pcaserecord);
begin
if p=nil then p:=hcaselabel
else
if (p^._low>hcaselabel^._low) and
(p^._low>hcaselabel^._high) then
insertlabel(p^.less)
else if (p^._high<hcaselabel^._low) and
(p^._high<hcaselabel^._high) then
insertlabel(p^.greater)
else Message(parser_e_double_caselabel);
end;
begin
new(hcaselabel);
hcaselabel^.less:=nil;
hcaselabel^.greater:=nil;
hcaselabel^.statement:=aktcaselabel;
getlabel(hcaselabel^._at);
hcaselabel^._low:=l;
hcaselabel^._high:=h;
insertlabel(wurzel);
end;
var
code,caseexpr,p,instruc,elseblock : ptree;
hl1,hl2 : longint;
ranges : boolean;
begin
consume(_CASE);
caseexpr:=expr;
{ determines result type }
cleartempgen;
do_firstpass(caseexpr);
casedef:=caseexpr^.resulttype;
if not(is_ordinal(casedef)) then
Message(parser_e_ordinal_expected);
consume(_OF);
wurzel:=nil;
ranges:=false;
instruc:=nil;
repeat
getlabel(aktcaselabel);
{aktcaselabel^.is_used:=true; }
{ an instruction has may be more case labels }
repeat
p:=expr;
cleartempgen;
do_firstpass(p);
if (p^.treetype=rangen) then
begin
{ type checking for case statements }
if not is_subequal(casedef, p^.left^.resulttype) then
Message(parser_e_case_mismatch);
{ type checking for case statements }
if not is_subequal(casedef, p^.right^.resulttype) then
Message(parser_e_case_mismatch);
hl1:=get_ordinal_value(p^.left);
hl2:=get_ordinal_value(p^.right);
testrange(casedef,hl1);
testrange(casedef,hl2);
newcaselabel(hl1,hl2);
ranges:=true;
end
else
begin
{ type checking for case statements }
if not is_subequal(casedef, p^.resulttype) then
Message(parser_e_case_mismatch);
hl1:=get_ordinal_value(p);
testrange(casedef,hl1);
newcaselabel(hl1,hl1);
end;
disposetree(p);
if token=COMMA then consume(COMMA)
else break;
until false;
consume(COLON);
{ handles instruction block }
p:=gensinglenode(labeln,statement);
p^.labelnr:=aktcaselabel;
{ concats instruction }
instruc:=gennode(anwein,instruc,p);
if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
consume(SEMICOLON);
until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
if (token=_ELSE) or (token=_OTHERWISE) then
begin
if token=_ELSE then consume(_ELSE)
else consume(_OTHERWISE);
elseblock:=statements_til_end;
end
else
begin
elseblock:=nil;
consume(_END);
end;
code:=gencasenode(caseexpr,instruc,wurzel);
code^.elseblock:=elseblock;
case_statement:=code;
end;
function repeat_statement : ptree;
var
first,last,p_e : ptree;
begin
consume(_REPEAT);
first:=nil;
while token<>_UNTIL do
begin
if first=nil then
begin
last:=gennode(anwein,nil,statement);
first:=last;
end
else
begin
last^.left:=gennode(anwein,nil,statement);
last:=last^.left;
end;
if token<>SEMICOLON then
break;
consume(SEMICOLON);
while token=SEMICOLON do
consume(SEMICOLON);
end;
consume(_UNTIL);
first:=gensinglenode(blockn,first);
p_e:=expr;
repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
end;
function while_statement : ptree;
var
p_e,p_a : ptree;
begin
consume(_WHILE);
p_e:=expr;
consume(_DO);
p_a:=statement;
while_statement